package com.sxjh.service.scalereport.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxjh.common.ZPage;
import com.sxjh.entity.param.DailyReportParam;
import com.sxjh.entity.param.ScaleReportParam;
import com.sxjh.entity.result.DailyReportResult;
import com.sxjh.entity.result.ScaleReportResult;
import com.sxjh.mapper.ScaleReportMapper;
import com.sxjh.service.scalereport.ScaleReportService;
import com.sxjh.uitl.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * @author zxz
 * @Date 2021/11/14
 * @Description:
 */
@Service
@Slf4j
public class ScaleReportServiceImpl implements ScaleReportService {

    @Resource
    private ScaleReportMapper scaleReportMapper;
//    @Resource
//    @Qualifier("taskExecutor")
//    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 过滤条件map
     */
    private static Map<String, String> FILTER_MAP = new HashMap<>();
    static {
        FILTER_MAP.put("companyName", "init_weight.company_name");
        FILTER_MAP.put("productName", "init_weight.product_name");
        FILTER_MAP.put("warehouseName", "case when generate_orders.warehouse_name IS NULL THEN warehouses.title ELSE generate_orders.warehouse_name END");
        FILTER_MAP.put("wuserName", "wuser.name");
        FILTER_MAP.put("shipmentSellerName", "trucking_orders.shipment_seller_name");
    }

    @Override
    public List<ScaleReportResult> getScaleReportByPageAll(ScaleReportParam param){
        Page<ScaleReportResult> iPage = new Page<>(1, -1);
        QueryWrapper<ScaleReportResult> queryTotalWrapper = this.queryFilter(param, true);
        IPage<ScaleReportResult> resultPage = scaleReportMapper.getScaleReportByPage(iPage, queryTotalWrapper);
        List<ScaleReportResult> scaleReportResultList = resultPage.getRecords();
        if(CollectionUtils.isEmpty(scaleReportResultList)){
            scaleReportResultList = new ArrayList<>();
        }
        return scaleReportResultList;
    }

    @Override
    public ZPage<ScaleReportResult> getScaleReportByPage(ScaleReportParam param){
        Page<ScaleReportResult> iPage = new Page<>(param.getCurr(), param.getPageSize());
        //设置自定义查询总数
        iPage.setSearchCount(Boolean.FALSE);
        StopWatch sw = new StopWatch("bd_query");
        sw.start("bd_page_query");
        QueryWrapper<ScaleReportResult> queryWrapper = this.queryFilter(param, false);
        IPage<ScaleReportResult> resultPage = scaleReportMapper.getScaleReportByPage(iPage, queryWrapper);
        sw.stop();
        List<ScaleReportResult> scaleReportResultList;
        //如果是点击分页或排序，不需要查询合计
        if(null == param.getIsQueryTotal() || param.getIsQueryTotal()){
            sw.start("bd_total_query");
            scaleReportResultList = this.getScaleReportByPageAll(param);
            sw.stop();
        }else{
            scaleReportResultList = new ArrayList<>();
        }
        resultPage.setTotal(scaleReportResultList.size());
        //处理总计数据
        sw.start("bd_total_handle_query");
        Map<String, Object> extend = this.handleTotalData(scaleReportResultList);
        sw.stop();
        System.out.println(sw.prettyPrint());
        return new ZPage(resultPage, extend);
    }

    /**
     * 处理合计数据
     * @param scaleReportResultList
     * @return
     */
    private Map<String, Object> handleTotalData(List<ScaleReportResult> scaleReportResultList){
        Integer factoryOutCount = 0; //已出厂总数
        Integer notFactoryOutCount = 0; //未出厂总数
        Integer carNumberCount = 0; //总车数
        HashSet<String>factoryOutCountSet=new HashSet<>();//记录已出厂总数
        HashMap<String, LocalDateTime>repetitionMap=new HashMap<>();//记录重复派车单数据
        Integer numSet = 0; //记录set容量变化
        BigDecimal mWeightNum = BigDecimal.ZERO; //毛重
        BigDecimal pWeightNum = BigDecimal.ZERO; //皮重
        BigDecimal weighbridgeWeightNum = BigDecimal.ZERO; //净重
        BigDecimal originalWeightNum = BigDecimal.ZERO; //结算量
        BigDecimal netWeightNum = BigDecimal.ZERO; //原发数
        Set<String> companyNameList = new HashSet<>();
        Set<String> productNameList = new HashSet<>();
        Set<String> warehouseNameList = new HashSet<>();
        Set<String> wuserNameList = new HashSet<>();
        Set<String> shipmentSellerNameList = new HashSet<>();
        for(ScaleReportResult reportResult : scaleReportResultList){
            //如果出场日期不为空
            if(reportResult.getFactoryOutTime() != null){
                //去重获取已出厂车数
                factoryOutCountSet.add(reportResult.getTruckingNo());
                numSet++;
                //数据发生变化说明有重复数据
                if (numSet>factoryOutCountSet.size()){
                    repetitionMap.put(reportResult.getTruckingNo(),reportResult.getFactoryOutTime());
                }
                //已出厂总数加1
//                factoryOutCount ++;
            }
//            else{
//
//                //否则未出厂总数加1
//                notFactoryOutCount ++;
//            }
            //如果车牌号不为空
//            if(StringUtils.isNotBlank(reportResult.getCarNumber())){
//                //总车数加1
//                carNumberCount ++;
//            }

            //毛重
            mWeightNum = mWeightNum.add(reportResult.getmWeight());
            //皮重
            pWeightNum = pWeightNum.add(reportResult.getpWeight());
            //净重
            weighbridgeWeightNum = weighbridgeWeightNum.add(reportResult.getWeighbridgeWeight());
            //结算量
            originalWeightNum = originalWeightNum.add(reportResult.getOriginalWeight());
            //原发数
            netWeightNum = netWeightNum.add(reportResult.getNetWeight());

            //处理过滤条件
            if(StringUtils.isNotBlank(reportResult.getCompanyName())){
                companyNameList.add(reportResult.getCompanyName());
            }
            if(StringUtils.isNotBlank(reportResult.getProductName())){
                productNameList.add(reportResult.getProductName());
            }
            if(StringUtils.isNotBlank(reportResult.getWarehouseName())){
                warehouseNameList.add(reportResult.getWarehouseName());
            }
            if(StringUtils.isNotBlank(reportResult.getWuserName())){
                wuserNameList.add(reportResult.getWuserName());
            }
            if(StringUtils.isNotBlank(reportResult.getShipmentSellerName())){
                shipmentSellerNameList.add(reportResult.getShipmentSellerName());
            }
        }
        //未出厂车数(去重后)
        List<Integer> notFactoryOutList=new ArrayList<>();
        notFactoryOutList.add(0);
        repetitionMap.forEach(
           (s,localDateTime)-> {
                if (localDateTime==null){
                    Integer num=notFactoryOutList.get(0);
                    num++;
                    notFactoryOutList.set(0,num);
                }
            }
        );
        factoryOutCount=factoryOutCountSet.size();
        notFactoryOutCount=notFactoryOutList.get(0);
        carNumberCount=factoryOutCount+notFactoryOutCount;
        Map<String, Object> map = new HashMap<>();
        map.put("factoryOutCount", factoryOutCount);
        map.put("notFactoryOutCount", notFactoryOutCount);
        map.put("carNumberCount", carNumberCount);
        map.put("mWeightNum", mWeightNum.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        map.put("pWeightNum", pWeightNum.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        map.put("weighbridgeWeightNum", weighbridgeWeightNum.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        map.put("originalWeightNum", originalWeightNum.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        map.put("netWeightNum", netWeightNum.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        map.put("total", scaleReportResultList.size());

        map.put("companyNameFilters", companyNameList);
        map.put("productNameFilters", productNameList);
        map.put("warehouseNameFilters", warehouseNameList);
        map.put("wuserNameFilters", wuserNameList);
        map.put("shipmentSellerNameFilters", shipmentSellerNameList);
        return map;
    }

    /**
     * 查询条件
     * @param param
     * @param queryCount 是否查询总数 true-是
     * @return
     */
    private QueryWrapper<ScaleReportResult> queryFilter(ScaleReportParam param, boolean queryCount){
        QueryWrapper<ScaleReportResult> queryWrapper = new QueryWrapper();
//        queryWrapper.isNull("weight_logs.deleted_at");
        queryWrapper.eq("trucking_orders.status", 1);
        if(StringUtils.isNotBlank(param.getCarNumber()))
            queryWrapper.like("init_weight.car_number", param.getCarNumber());
        if(StringUtils.isNotBlank(param.getCompanyName()))
            queryWrapper.like("init_weight.company_name", param.getCompanyName());
        if(StringUtils.isNotBlank(param.getProductName()))
            queryWrapper.like("init_weight.product_name", param.getProductName());
        if(StringUtils.isNotBlank(param.getWeightNo()))
            queryWrapper.like("init_weight.weight_no", param.getWeightNo());
        if(StringUtils.isNotBlank(param.getWarehouseName()))
            queryWrapper.like("generate_orders.warehouse_name", param.getWarehouseName());
        if(StringUtils.isNotBlank(param.getWuserName()))
            queryWrapper.like("wuser.name", param.getWuserName());
        if(param.getCategoryId() != null)
            queryWrapper.eq("materials.category_id", param.getCategoryId());
        if(param.getDischargeStage() != null)
            queryWrapper.eq("vehicle_base_infos.discharge_stage", param.getDischargeStage());

        if(param.getStartDate() != null && param.getEndDate() != null){
            Integer way = param.getWay();
            if(way != null && way.intValue() == 0){
                queryWrapper.ge("trucking_orders.factory_in_time", param.getStartDate());
                queryWrapper.le("trucking_orders.factory_in_time", param.getEndDate());
            }else if(way != null && way.intValue() == 1){
                queryWrapper.ge("trucking_orders.factory_out_time", param.getStartDate());
                queryWrapper.le("trucking_orders.factory_out_time", param.getEndDate());
            }
        }
        //处理过滤条件
        Map<String, String> filterParamMap = param.getFilterParamMap();
        if(filterParamMap != null){
            for(Map.Entry<String, String> entry : filterParamMap.entrySet()){
                String filterValue = entry.getValue();
                if(StringUtils.isBlank(filterValue)){
                    continue;
                }
                String filterField = entry.getKey();
                if(FILTER_MAP.containsKey(filterField)){
                    queryWrapper.eq(FILTER_MAP.get(filterField), filterValue);
                }
            }
        }
        //如果是查询总数，不需要排序
        if(queryCount){
            return queryWrapper;
        }
        //排序
        if(StringUtils.isNotBlank(param.getSortField()) && StringUtils.isNotBlank(param.getSortOrder())){
            if("desc".equalsIgnoreCase(param.getSortOrder())){
                queryWrapper.orderByDesc(param.getSortField());
            }
            if("asc".equalsIgnoreCase(param.getSortOrder())){
                queryWrapper.orderByAsc(param.getSortField());
            }
        }
        return queryWrapper;
    }

    /**
     * 磅单报表（逻辑分页）
     * @param param
     * @return
     */
    @Override
    public PageUtil<ScaleReportResult> getScaleReport(ScaleReportParam param) {
        PageUtil<ScaleReportResult> pageUtil = new PageUtil<>();
        PageUtil<ScaleReportResult> resultPage = new PageUtil<>();
        if(param.getCurr() !=0 && param.getPageSize() != 0){
            pageUtil.setPageNum(param.getCurr());
            pageUtil.setPageSize(param.getPageSize());
            resultPage = pageUtil.setMyList(scaleReportMapper.getScaleReport(param));
            resultPage.setPageCount(pageUtil.getMyList().size());
            return resultPage;
        }
        return resultPage.setMyList(scaleReportMapper.getScaleReport(param));
    }

    @Override
    public List<ScaleReportResult> getScaleReport2(ScaleReportParam param) {
        List<ScaleReportResult> list = scaleReportMapper.getScaleReport(param);
        int index = 1;
        for (ScaleReportResult scaleReportResult : list) {
            scaleReportResult.setIndex(index);
            switch (scaleReportResult.getDischargeStage()){
                case 0:
                    scaleReportResult.setEmissions("国0");
                    break;
                case 1:
                    scaleReportResult.setEmissions("国一");
                    break;
                case 2:
                    scaleReportResult.setEmissions("国二");
                    break;
                case 3:
                    scaleReportResult.setEmissions("国三");
                    break;
                case 4:
                    scaleReportResult.setEmissions("国四");
                    break;
                case 5:
                    scaleReportResult.setEmissions("国五");
                    break;
                case 6:
                    scaleReportResult.setEmissions("国六");
                    break;
                case 7:
                    scaleReportResult.setEmissions("电动");
                    break;
            }
            index++;
        }
        return list;
    }

    @Override
    public PageUtil<ScaleReportResult> getScaleReport3(ScaleReportParam param) {
        PageUtil<ScaleReportResult> resultPage = new PageUtil<>();
//        if(!StringUtils.isEmpty(param.getCompanyName()) && !StringUtils.isEmpty(param.getCarriersName())){
//            param.setSupplierQM(1);
//        }else {
//            param.setSupplierQM(0);
//        }
        resultPage.setPageNum(param.getCurr());
        resultPage.setPageSize(param.getPageSize());
        resultPage.setMyList(scaleReportMapper.getScaleReport(param));
        resultPage.setPageCount(resultPage.getMyList().size());
        int index = 1;
        for (ScaleReportResult datum : resultPage.getData()) {
            datum.setIndex(index);
            switch (datum.getDischargeStage()){
                case 0:
                    datum.setEmissions("国0");
                    break;
                case 1:
                    datum.setEmissions("国一");
                    break;
                case 2:
                    datum.setEmissions("国二");
                    break;
                case 3:
                    datum.setEmissions("国三");
                    break;
                case 4:
                    datum.setEmissions("国四");
                    break;
                case 5:
                    datum.setEmissions("国五");
                    break;
                case 6:
                    datum.setEmissions("国六");
                    break;
                case 7:
                    datum.setEmissions("电动");
                    break;
            }
            index++;
        }
        return resultPage;

    }


    /**
     * 日报表
     * @param param
     * @return
     */
    @Override
    public List<DailyReportResult> getDailyReport(DailyReportParam param) {
        List<DailyReportResult> result=new ArrayList<>();
        List<DailyReportResult> dailyReportResultList = scaleReportMapper.getDailyReport(param);
        if (dailyReportResultList.size()<1){
            return dailyReportResultList;
        }
        Map<String, List<DailyReportResult>> collect1 = dailyReportResultList.stream()
                .collect(Collectors.groupingBy(DailyReportResult::getProductName, Collectors.toList()));
        DailyReportResult dailyReportResulthj = new DailyReportResult();
        dailyReportResulthj.setProductName("合计");
        dailyReportResulthj.setCarNumber(new BigDecimal(dailyReportResultList.size()));
        for (String str:collect1.keySet()) {
            Map<String, List<DailyReportResult>> collect2 = collect1.get(str).stream()
                    .collect(Collectors.groupingBy(DailyReportResult::getCompanyName, Collectors.toList()));
            DailyReportResult dailyReportResultxj = new DailyReportResult();
            dailyReportResultxj.setCompanyName("小计");
            dailyReportResultxj.setCarNumber(new BigDecimal(collect1.get(str).size()));
            for (String str1:collect2.keySet()) {
                DailyReportResult dailyReportResultgs = new DailyReportResult();
                dailyReportResultgs.setCarNumber(new BigDecimal(collect2.get(str1).size()));
                //累计公司的车数和吨数
                for (DailyReportResult dailyReportResult:collect2.get(str1)) {
                    dailyReportResultgs.setCompanyName(dailyReportResult.getCompanyName());
                    dailyReportResultgs.setProductName(dailyReportResult.getProductName());
                    dailyReportResultgs.setTonnes(dailyReportResultgs.getTonnes().add(dailyReportResult.getTonnes()));
                    dailyReportResultgs.setNetWeight(dailyReportResultgs.getNetWeight().add(dailyReportResult.getNetWeight()));
                    dailyReportResultgs.setOriginalWeight(dailyReportResultgs.getOriginalWeight().add(dailyReportResult.getOriginalWeight()));
                }
                result.add(dailyReportResultgs);
                dailyReportResultxj.setProductName(dailyReportResultgs.getProductName());
                dailyReportResultxj.setTonnes(dailyReportResultxj.getTonnes().add(dailyReportResultgs.getTonnes()));
                dailyReportResultxj.setNetWeight(dailyReportResultxj.getNetWeight().add(dailyReportResultgs.getNetWeight()));
                dailyReportResultxj.setOriginalWeight(dailyReportResultxj.getOriginalWeight().add(dailyReportResultgs.getOriginalWeight()));
            }
            result.add(dailyReportResultxj);
            dailyReportResulthj.setTonnes(dailyReportResulthj.getTonnes().add(dailyReportResultxj.getTonnes()));
            dailyReportResulthj.setNetWeight(dailyReportResulthj.getNetWeight().add(dailyReportResultxj.getNetWeight()));
            dailyReportResulthj.setOriginalWeight(dailyReportResulthj.getOriginalWeight().add(dailyReportResultxj.getOriginalWeight()));
        }
        result.add(dailyReportResulthj);
        return result;
    }

    @Override
    public List<DailyReportResult> getWareHousesReport(DailyReportParam param) {
        List<DailyReportResult> result=new ArrayList<>();
        List<DailyReportResult> dailyReportResultList = scaleReportMapper.getDailyReport(param);
        if (dailyReportResultList.size()<1){
            return dailyReportResultList;
        }
        Map<String, List<DailyReportResult>> collect1 = dailyReportResultList.stream()
                .collect(Collectors.groupingBy(DailyReportResult::getWareHouseName, Collectors.toList()));
        DailyReportResult dailyReportResulthj = new DailyReportResult();
        dailyReportResulthj.setWareHouseName("合计");
        dailyReportResulthj.setCarNumber(new BigDecimal(dailyReportResultList.size()));
        for (String str:collect1.keySet()) {
            Map<String, List<DailyReportResult>> collect2 = collect1.get(str).stream()
                    .collect(Collectors.groupingBy(DailyReportResult::getProductName, Collectors.toList()));
            DailyReportResult dailyReportResultxj = new DailyReportResult();
            dailyReportResultxj.setProductName("小计");
            dailyReportResultxj.setCarNumber(new BigDecimal(collect1.get(str).size()));
            for (String str1:collect2.keySet()) {
                DailyReportResult dailyReportResultgs = new DailyReportResult();
                dailyReportResultgs.setCarNumber(new BigDecimal(collect2.get(str1).size()));
                //累计公司的车数和吨数
                for (DailyReportResult dailyReportResult:collect2.get(str1)) {
                    dailyReportResultgs.setProductName(dailyReportResult.getProductName());
                    dailyReportResultgs.setWareHouseName(dailyReportResult.getWareHouseName());
                    dailyReportResultgs.setTonnes(dailyReportResultgs.getTonnes().add(dailyReportResult.getTonnes()));
                    dailyReportResultgs.setNetWeight(dailyReportResultgs.getNetWeight().add(dailyReportResult.getNetWeight()));
                    dailyReportResultgs.setOriginalWeight(dailyReportResultgs.getOriginalWeight().add(dailyReportResult.getOriginalWeight()));
                }
                result.add(dailyReportResultgs);
                dailyReportResultxj.setWareHouseName(dailyReportResultgs.getWareHouseName());
                dailyReportResultxj.setTonnes(dailyReportResultxj.getTonnes().add(dailyReportResultgs.getTonnes()));
                dailyReportResultxj.setNetWeight(dailyReportResultxj.getNetWeight().add(dailyReportResultgs.getNetWeight()));
                dailyReportResultxj.setOriginalWeight(dailyReportResultxj.getOriginalWeight().add(dailyReportResultgs.getOriginalWeight()));
            }
            result.add(dailyReportResultxj);
            dailyReportResulthj.setTonnes(dailyReportResulthj.getTonnes().add(dailyReportResultxj.getTonnes()));
            dailyReportResulthj.setNetWeight(dailyReportResulthj.getNetWeight().add(dailyReportResultxj.getNetWeight()));
            dailyReportResulthj.setOriginalWeight(dailyReportResulthj.getOriginalWeight().add(dailyReportResultxj.getOriginalWeight()));
        }
        result.add(dailyReportResulthj);
        return result;
    }
}

